{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Wealth Of Nations Dashboard\n",
    "1. Use the dropdown to select the data type\n",
    "2. Use the slider to show the heatmap for a specific year\n",
    "3. Use the animation button to animate the choropleth for all the years\n",
    "4. Clicking on any country toggles the display of timeseries for that country. (Clicking on oceans un-selects all the countries)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "\n",
    "import ipywidgets as widgets\n",
    "import bqplot as bq\n",
    "import bqplot.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "initial_year = 1800"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "data = pd.read_json('nations.json')\n",
    "country_codes = pd.read_csv('world_map_codes.csv')\n",
    "country_code_map = dict(zip(country_codes['ISON3'], country_codes['Name']))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "country_data = data.merge(country_codes, \n",
    "                          left_on='name', \n",
    "                          right_on='Name')[['name', 'ISON3', 'region', 'income', 'lifeExpectancy', 'population']]\\\n",
    "    .rename(columns={'ISON3': 'id'})\\\n",
    "    .set_index('id')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_time_series(col):\n",
    "    time_series_df = country_data[col]\\\n",
    "        .apply(dict)\\\n",
    "        .apply(pd.Series)\n",
    "    time_series_df.index.name = None\n",
    "    time_series_df.columns = time_series_df.columns.astype('int')\n",
    "    \n",
    "    return time_series_df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "income_time_series = get_time_series('income')\n",
    "life_exp_time_series = get_time_series('lifeExpectancy')\n",
    "pop_time_series = get_time_series('population')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "income_min, income_max = income_time_series.min().min(), income_time_series.max().max()\n",
    "life_exp_min, life_exp_max = life_exp_time_series.min().min(), life_exp_time_series.max().max()\n",
    "pop_min, pop_max = pop_time_series.min().min(), pop_time_series.max().max()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "data_dict = {'Income': income_time_series,\n",
    "             'Population': pop_time_series,\n",
    "             'Life Expectancy': life_exp_time_series}\n",
    "\n",
    "min_max_dict = {'Income': (np.log(income_min), np.log(income_max)), \n",
    "                'Population': (np.log(pop_min), np.log(pop_max)),\n",
    "                'Life Expectancy': (life_exp_min, life_exp_max)}\n",
    "\n",
    "color_scheme_dict = {'Income': 'Greens',\n",
    "                     'Population': 'Blues',\n",
    "                     'Life Expectancy': 'Oranges'}\n",
    "\n",
    "data_type_dropdown = widgets.Dropdown(description='Data Type', \n",
    "                                      options=['Income', 'Life Expectancy', 'Population'],\n",
    "                                      value='Population')\n",
    "\n",
    "year_slider = widgets.IntSlider(description='year', min=1800, max=2008, \n",
    "                                continuous_update=False,\n",
    "                                layout=widgets.Layout(width='300px'))\n",
    "\n",
    "play_button = widgets.Play(min=1800, max=2008, interval=10)\n",
    "widgets.jslink((play_button, 'value'), (year_slider, 'value'))\n",
    "\n",
    "# world map\n",
    "world_map_fig_title_tmpl = 'World {data_type} for year {year}'\n",
    "world_map_fig = plt.figure(layout=widgets.Layout(width='1000px', height='500px'),\n",
    "                           fig_margin=dict(top=45, bottom=10, left=20, right=20))\n",
    "tooltip = bq.Tooltip(fields=['name'], labels=['Country'])\n",
    "\n",
    "plt.scales(scales={'projection': bq.Mercator(), 'color': bq.ColorScale()})\n",
    "\n",
    "world_map = plt.geo(map_data='WorldMap', tooltip=tooltip, \n",
    "                    interactions={'click': 'select', 'hover': 'tooltip'},\n",
    "                    axes_options={'color': {'visible': False}},\n",
    "                    selected_styles={'selected_fill': 'yellow'},\n",
    "                    colors={'default_color': 'Grey'})\n",
    "\n",
    "# data time series fig\n",
    "ts_fig_title_tmpl = '{data_type} Time Series'\n",
    "time_series_fig = plt.figure(layout=widgets.Layout(width='1000px', height='400px'),\n",
    "                             fig_margin=dict(top=40, bottom=30, left=60, right=40))\n",
    "country_time_series = plt.plot(list(pop_time_series.columns), [], \n",
    "                               axes_options={'x': {'label': 'Year'},\n",
    "                                             'y': {'tick_format': '~s'}},\n",
    "                               display_legend=True)\n",
    "\n",
    "# link widgets\n",
    "def on_data_type_update(*args):\n",
    "    global data_time_series\n",
    "    # reset color and selected attributes of world_map\n",
    "    world_map.color = {}\n",
    "    world_map.selected = []\n",
    "    \n",
    "    data_type = data_type_dropdown.value\n",
    "    data_time_series = data_dict[data_type]\n",
    "    \n",
    "    scale_min, scale_max = min_max_dict[data_type]\n",
    "    color_scale = world_map.scales['color']\n",
    "    color_scale.scheme = color_scheme_dict[data_type]\n",
    "    color_scale.min = scale_min\n",
    "    color_scale.max = scale_max\n",
    "    year_slider.value = initial_year\n",
    "\n",
    "data_type_dropdown.observe(on_data_type_update, 'value')\n",
    "    \n",
    "def update_color(*args):\n",
    "    data_type = data_type_dropdown.value\n",
    "    year = year_slider.value\n",
    "    \n",
    "    if year in data_time_series.columns:\n",
    "        if data_type in ['Population', 'Income']:\n",
    "            color_data = np.log(data_time_series[year])\n",
    "        else:\n",
    "            color_data = data_time_series[year]\n",
    "        world_map.color = dict(color_data)\n",
    "    else:\n",
    "        world_map.color = {}\n",
    "    \n",
    "    world_map_fig.title = world_map_fig_title_tmpl.format(data_type=data_type, year=year)\n",
    "\n",
    "year_slider.observe(update_color, 'value')\n",
    "\n",
    "def plot_time_series_for_country(*args):\n",
    "    if world_map.selected is not None and len(world_map.selected) > 0:\n",
    "        selected_countries = world_map.selected\n",
    "        country_time_series.y = data_time_series.loc[selected_countries]\n",
    "        country_time_series.labels = [country_code_map[c_id] for c_id in selected_countries]\n",
    "    else:\n",
    "        country_time_series.labels = []\n",
    "        country_time_series.y = []\n",
    "    time_series_fig.title = ts_fig_title_tmpl.format(data_type=data_type_dropdown.value)\n",
    "world_map.observe(plot_time_series_for_country, 'selected')\n",
    "    \n",
    "on_data_type_update(None)\n",
    "\n",
    "widgets.VBox([world_map_fig, \n",
    "              widgets.HBox([time_series_fig, \n",
    "              widgets.VBox([data_type_dropdown, year_slider, play_button])])\n",
    "             ])"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
